#include <iostream>
#include <string>
#include <fstream>
#include "contacts.pb.h"

using namespace std;

void AddPeopleInfo(contacts2::PeopleInfo* people)
{
    cout << "-----------新增联系人---------" << endl;

    cout << "请输入联系人姓名：";
    string name;
    getline(cin, name);
    people->set_name(name);

    cout << "请输入联系人年龄：";
    int age;
    cin >> age;
    people->set_age(age);
    cin.ignore(256, '\n');//是 C++ 中用于清理输入缓冲区（input buffer）的常用方法，
    //主要目的是防止因残留的换行符或多余字符导致后续输入出错

    for(int i=0; ; i++)
    {
        cout << "请输入联系人电话" << i + 1 << "(只输入回车完成电话新增):";
        string number;
        getline(cin, number);
        if(number.empty()){
            break;
        }
        contacts2::PeopleInfo_Phone* phone = people->add_phone();
        phone->set_number(number);

        cout << "请输入该电话类型（1.移动电话 2.固定电话）: " << endl;
        int type;
        cin >> type;
        cin.ignore(256, '\n');
        switch(type){
            case 1:
                phone->set_type(contacts2::PeopleInfo_Phone_PhoneType::PeopleInfo_Phone_PhoneType_MP);
                break;
            case 2:
                phone->set_type(contacts2::PeopleInfo_Phone_PhoneType::PeopleInfo_Phone_PhoneType_TEL);
                break;
            default:
                cout << "选择错误" << endl;
                break;
        } 
    }

    contacts2::Address address;
    cout << "请输入家庭地址: " << endl;
    string home_address;
    getline(cin, home_address);
    address.set_home_address(home_address);

    cout << "请输入单位地址: " << endl;
    string unit_address;
    getline(cin, unit_address);
    address.set_unit_address(unit_address);
    // Address->Any
    people->mutable_data()->PackFrom(address);

    cout << "请选择要添加的联系方式(1.qq   2.微信): " << endl;
    int other_contact;
    cin >> other_contact;
    cin.ignore(256, '\n');
    if(1 == other_contact)
    {
        cout << "请输入联系人QQ: " << endl;
        string qq;
        getline(cin, qq);
        people->set_qq(qq);
    }
    else if(2 == other_contact)
    {
        cout << "请输入联系人微信: " << endl;
        string wx;
        getline(cin, wx);
        people->set_wechat(wx);
    }
    else{
        cout << "选择错误"  << endl;
    }

    for(int i=0; ; i++)
    {
        cout << "请输入备注" << i+1 << "标题(输入回车完成新增):" << endl;
        string remark_key;
        getline(cin, remark_key);
        if(remark_key.empty())
        {
            break;
        }

        cout << "请输入备注" << i+1 << "内容: " << endl;
        string remark_value;
        getline(cin, remark_value);
        people->mutable_remark()->insert({remark_key, remark_value});
    } 

    cout << "---------新增成功-------------" << endl; 
}

void Write()
{
    contacts2::Contacts contacts;
    // 读取本地已存在的通讯录文件
    fstream input("contacts.bin", ios::in | ios::binary);
    if(!input)
    {
        cout << "打开文件失败，先创建" << endl;
    }
    else if(!contacts.ParseFromIstream(&input)){
        cout << "反序列化失败" << endl;
        input.close();
        return;
    }
    // 向通讯录添加一个联系人
    AddPeopleInfo(contacts.add_contacts());

    // 将通讯录写入本地文件
    fstream output("contacts.bin", ios::out | ios::trunc | ios::binary);
    if(!contacts.SerializeToOstream(&output)){
        cout << "写入失败" << endl;
        input.close();
        output.close();
        return;
    }
    cout << "写入成功" << endl;
    input.close();
    output.close();
}

void PrintContacts(contacts2::Contacts& contacts)
{
    for(int i=0; i<contacts.contacts_size(); i++)
    {
        cout << "------------联系人" << i + 1 << "-------------" << endl;
        const contacts2::PeopleInfo& people = contacts.contacts(i);
        cout << "联系人姓名：" << people.name() << endl;
        cout << "联系人年龄：" << people.age() << endl;
        for(int j=0; j<people.phone_size(); j++)
        {
            const contacts2::PeopleInfo_Phone& phone = people.phone(j);
            cout << "联系人电话: " << j+1 << ":" << phone.number() << endl;

            // 联系人电话
            cout << "  (" << phone.PhoneType_Name(phone.type()) << ")" << endl;
        }
        if(people.has_data() && people.data().Is<contacts2::Address>())
        {
            contacts2::Address address;
            people.data().UnpackTo(&address);
            if(!address.home_address().empty()){
                cout << "家庭地址: " << address.home_address() << endl;
            }
            if(!address.unit_address().empty()){
                cout << "单位地址: " << address.unit_address() << endl;
            }
        }

        switch(people.other_contact_case())
        {
            case contacts2::PeopleInfo::OtherContactCase::kQq:
                cout << "联系人QQ: " << people.qq() << endl;
                break;
            case contacts2::PeopleInfo::OtherContactCase::kWechat:
                cout << "联系人wx: " << people.wechat() << endl;
                break;
            default:
                break;
        }

        if(people.remark_size())
        {
            cout << "备注信息: " << endl;
        }
        for(auto it = people.remark().cbegin(); it != people.remark().cend(); it++)
        {
            cout << "  " << it->first << ": " << it->second << endl;
        }
    }
}

void Read()
{
    contacts2::Contacts contacts;
    // 读取本地已存在的通讯录文件
    fstream input("contacts.bin", ios::in | ios::binary);
    if(!input)
    {
        cout << "打开文件失败，先创建" << endl;
    }
    else if(!contacts.ParseFromIstream(&input)){
        cout << "反序列化失败" << endl;
        input.close();
        return;
    }

    // 打印通讯录列表
    PrintContacts(contacts);
}

int main()
{
    Write();

    Read();
    return 0;
}